package com.sias.reflection.classload;


/**
 * @author 吴文杰
 * @version 1.0
 * @createTime 2023-05-02 15:06:05
 */
@SuppressWarnings("all")
public class ClassLoad {
  public static void main(String[] args) throws ClassNotFoundException {
    /**
     * 1.加载B类，并生成B的Class对象
     * 2.连接 num=0；
     * 3.初始化阶段 ：依次进行收集类中的所有静态变量的赋值动作和静态代码块中的语句，并进行合并
     *    clinit（）{
     *      System.out.println("B的静态代码块被执行");
     *      //num = 300;
     *      num = 100
     *    }
     */
    // new B();
    // System.out.println(B.num);
    // Class<?> cls = Class.forName("com.sias.reflection.classload.B");
    B b = new B();
  }
}


@SuppressWarnings("all")
class A {

  /**
   * 1.加载Loading
   *
   * 将字节码文件从不同的数据源(class文件、jar包等)转化为二进制字节流加载到内存，并为之创建一个java.lang.Class对象   类的字节码二进制数据存入方法区    Class类对象在堆中创建
   */

  /**
   * 2.1 linking  ====>  将类的二进制数据合并到jre中
   * -------验证verfication
   * 文件格式验证、元数据验证、字节码验证、符号引用验证等
   */

  /**
   * 2.2 linking
   * -------准备阶段Perparation
   * JVM会在该阶段对静态变量，分配内存并默认初始化(对应数据类型的默认初始值，如0、0L、null、false等)
   * 这些变量所用的内存都将在方法区中进行分配
   */
  //1.n1是实例变量  不是静态变量，在准备阶段是不会分配内存的
  //2.n2是静态变量  准备阶段 分配内存 n2 是默认初始化 0 而不是20
  //3.n3是static final 是常量  和静态变量不同  一但赋值就不变了  准备阶段n3 = 30
  public int n1 = 10;
  public static int n2 = 20;
  public static final int n3 = 30;
  /**
   * 2.3 linking
   * -------解析阶段resolution
   * 虚拟机将常量池内的符号引用替换为直接引用的过程
   *
   * 如A ox0011--> class
   */

  /**
   * 3.初始化阶段
   * 1.真正执行类中定义的Java程序代码，此阶段是执行<clinit>()方法的过程
   * 2.<clinit>()方法是由编译器按语句在源文件中出现顺序，依次进行收集类中的所有静态变量的赋值动作和静态代码块中的语句，并进行合并
   * 3.虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确地加锁、同步，如果多个线程同时去初始化一个类，
   *         那么只会有一个线程去执行这个类的<clinit>()方法，其他线程都需要阻塞等待，直到活动线程执行<clinit>()方法完
   */
}

class B {
  static {
    System.out.println("B的静态代码块被执行");
    num = 300;
  }

  static int num = 100;

  public B(){
    System.out.println("B的构造器被执行");
  }
}